package processor;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import static parser.MySimpleNode.errorExit;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

public class NodeHelp {
	static int i = 0;

	public static Node parent(Node base) {
		Node retval = base.getParentNode();
		while (retval.getNodeType() != Node.ELEMENT_NODE) {
			retval = retval.getParentNode();
		}
		return retval;
	}

	public static List<Node> children(Node parent) {
		List<Node> retval = new ArrayList<Node>();
		for (Node childNode = parent.getFirstChild(); childNode != null;) {
			Node nextChild = childNode.getNextSibling();
			if (childNode.getNodeType() == Node.ELEMENT_NODE)
				retval.add(childNode);
			childNode = nextChild;
		}
		return retval;
	}

	public static List<Node> descendants(Node root) {
		List<Node> retval = new ArrayList<Node>();
		Queue<Node> toProcess = new LinkedList<Node>();
		toProcess.add(root);
		Node working;
		// First case separated since a node is not its own descendant
		working = toProcess.poll();
		toProcess.addAll(children(working));
		while (!toProcess.isEmpty()) {
			working = toProcess.poll();
			toProcess.addAll(children(working));
			retval.add(working);
		}
		return retval;
	}

	public static Element makeElem(String tag, List<Node> list, Document doc) {
		Element elem = doc.createElement(tag);
		if (list != null)
			for (Node n : list) {
				// Need to make a copy in the new document
				Node imported = doc.importNode(n, true);
				elem.appendChild(imported);
			}
		return elem;
	}

	public static Text makeText(String value, Document doc) {
		Text textNode = doc.createTextNode(value);
		return textNode;
	}

	// Take in two tuples, and return their cross product
	public static Element crossProduct(Node t1, Node t2, Document doc) {
		List<Node> crossProduct = NodeHelp.children(t1);
		crossProduct.addAll(NodeHelp.children(t2));
		return makeElem("tuple", crossProduct, doc);
	}

	// Returns the subset of input list with duplicates removed
	public static List<Node> unique(List<Node> inList) {
		List<Node> retval = new ArrayList<Node>();
		for (Node n : inList) {
			boolean safe = true;
			for (Node m : retval) {
				if (n.isSameNode(m)) {
					safe = false;
					break;
				}
			}
			if (safe)
				retval.add(n);
		}
		return retval;
	}

	public static int numChildren(Node node) {
		return children(node).size();
	}

}
